#pragma once
#include "ll/api/event/Event.h"
#include <ll/api/event/entity/ActorEvent.h>
#include <ll/api/memory/Hook.h>
#include <ll/api/event/Cancellable.h>
#include <ll/api/event/player/PlayerEvent.h>
#include <ll/api/event/EventBus.h>
#include <ll/api/service/Service.h>
#include <mc/world/level/block/actor/PistonBlockActor.h>
#include <mc/network/ServerNetworkHandler.h>
#include <mc/world/actor/player/Player.h>
#include <mc/world/level/block/Block.h>
#include <mc/world/ActorRuntimeID.h>
#include <mc/world/ActorUniqueID.h>
#include <mc/world/actor/Actor.h>
#include <mc/world/level/Level.h>
#include <mc/world/actor/common/ClipDefaults.h>
#include <mc/world/level/block/LiquidBlockDynamic.h>
#include <mc/world/level/BlockSource.h>

namespace XD::Event {
    void entityRideEvent();             // 。。。
    void playerInteractEntityEvent();   // 与实体交互事件
    void pistonPushEvent();             // 活塞推动事件
    void explodeEvent();                // 爆炸事件
    void liquidFlowEvent();             // 液体流动事件

    class PlayerInteractEntityEvent final : public ll::event::Cancellable<ll::event::player::PlayerEvent> {
        public:
        Actor* mEntity;
        constexpr explicit PlayerInteractEntityEvent(Player& player, Actor* entity) : Cancellable(player), mEntity(entity) {}
    };

    class EntityRideEvent final : public ll::event::Cancellable<ll::event::ActorEvent> {
        public:
        constexpr explicit EntityRideEvent(Actor& ac) : Cancellable(ac) {}
    };

    class PistonPushEvent final : public ll::event::Cancellable<ll::event::Event> {
        public:
        BlockSource& region;
        BlockPos const& curPos;
        uchar curBranchFacing;
        uchar pistonMoveFacing;
        constexpr explicit PistonPushEvent(BlockSource& region, BlockPos const& curPos, uchar curBranchFacing, uchar pistonMoveFacing) 
            : Cancellable(), region(region), curPos(curPos), curBranchFacing(curBranchFacing),  pistonMoveFacing(pistonMoveFacing) {}
    };

    class ExplodeEvent final : public ll::event::Cancellable<ll::event::Event> {
        public:
        BlockSource& region;
        Actor*       source;
        Vec3 const&  pos;
        float        explosionRadius;
        constexpr explicit ExplodeEvent(
            BlockSource& region,
            Actor*       source,
            Vec3 const&  pos,
            float        explosionRadius
        ) : Cancellable(), region(region), source(source), pos(pos), explosionRadius(explosionRadius) {}
    };

    class LiquidFlowEvent final : public ll::event::Cancellable<ll::event::Event> {
        public:
        BlockSource&    region;
        BlockPos const& pos;
        BlockPos const& flowFromPos;
        uchar           flowFromDirection;
        constexpr explicit LiquidFlowEvent (
            BlockSource&    region,
            BlockPos const& pos,
            BlockPos const& flowFromPos,
            uchar           flowFromDirection
        ) : Cancellable(), region(region), pos(pos), flowFromPos(flowFromPos), flowFromDirection(flowFromDirection) {}
    };
}
